package com.ctrip.openapi.java.customed;

import java.io.IOException;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import org.xml.sax.InputSource;

import com.ctrip.openapi.java.base.DBPool;
import com.ctrip.openapi.java.base.DateUtil;
import com.ctrip.openapi.java.base.HttpAccessAdapter;
import com.ctrip.openapi.java.base.model.City;
import com.ctrip.openapi.java.base.model.PriceCache;
import com.ctrip.openapi.java.base.model.PricePlan;
import com.ctrip.openapi.java.base.model.PriceUpdateHistory;
import com.ctrip.openapi.java.base.model.Room;
import com.ctrip.openapi.java.utils.ConfigData;
import com.ctrip.openapi.java.utils.SignatureUtils;


public class HotelPriceCacheInfoAdapter {
	
   //ctripinterface 
	private static String createHotelCacheRatePlanRequestXml(String time,String cityCode){
		StringBuilder sb = new StringBuilder();
		try {
			sb.append("<Request><Header AllianceID=\"");
			sb.append(ConfigData.AllianceId);
			sb.append("\" SID=\"");
			sb.append(ConfigData.SId);
			sb.append("\" TimeStamp=\"");
			long timestamp = SignatureUtils.GetTimeStamp();
			sb.append(timestamp);
			sb.append("\" Signature=\"");

			String signature = SignatureUtils.CalculationSignature(timestamp
					+ "", ConfigData.AllianceId, ConfigData.SecretKey,
					ConfigData.SId, ConfigData.OTA_HotelCacheRatePlan);
			sb.append(signature);
			sb.append("\" RequestType=\"");
			sb.append(ConfigData.OTA_HotelCacheRatePlan);
			sb.append("\" /><HotelRequest><RequestBody xmlns:ns=\"http://www.opentravel.org/OTA/2003/05\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ns:OTA_HotelCacheChangeRQ  Version=\"1.0\" TimeStamp=\"");
			sb.append(DateUtil.getDateTimeForInterface("yyyy-MM-dd",new Date()));
			sb.append("\" ><ns:CacheSearchCriteria  CacheFromTimestamp=\"");
            sb.append(time);
            sb.append("\"><ns:CacheSearchCriterion HotelCityCode=\""+cityCode+"\" />");
            sb.append("</ns:CacheSearchCriteria></ns:OTA_HotelCacheChangeRQ></RequestBody></HotelRequest></Request>");
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}

		return sb.toString();
	}
	
	@SuppressWarnings("unchecked")
	private static List<PriceCache> findHotelCacheRatePlan(String time,String cityCode){
	
		List<PriceCache> pricePlanList=new ArrayList<PriceCache>();
		String response=HttpAccessAdapter.getResponseFromCtrip(ConfigData.OTA_HotelCacheRatePlan,
				HotelPriceCacheInfoAdapter.createHotelCacheRatePlanRequestXml(time,cityCode));
		
		//System.out.println(response);
      
		StringReader read = new StringReader(response);
        InputSource source = new InputSource(read);
      
        SAXBuilder builder = new SAXBuilder();
        try {      
        	 Document doc = builder.build(source);  
        	 Element root = doc.getRootElement();

        	 XPath rateXPath = XPath.newInstance("//ns:CacheChangeInfo");
        	 rateXPath.addNamespace("ns", "http://www.opentravel.org/OTA/2003/05");
        	
			 List<Element> ratelist =(List<Element>)rateXPath.selectNodes(root);
        	// System.out.println(ratelist.size());
			 for(int i=0;i<ratelist.size();i++){
				 Element ccif=ratelist.get(i);
				 Element ts=(Element)(ccif.getChildren().get(0));
				 Element oi=(Element)(ccif.getChildren().get(1));
				 PriceCache pc=new PriceCache();
				 pc.setRatePlanCode(oi.getAttributeValue("RatePlanCode"));
				 pc.setStart(ts.getAttributeValue("Start"));
				 pc.setEnd(ts.getAttributeValue("End"));
				 pc.setHotelCode(ccif.getAttributeValue("HotelCode"));
				 pricePlanList.add(pc);
			 }
		}catch (JDOMException e) {    
    		e.printStackTrace(); 
    		} catch (IOException e) {  
    			e.printStackTrace(); 
    			}
    			
       return pricePlanList;
	}

	
	@SuppressWarnings("unchecked")
	private static List<PricePlan> findHotelRatePlan(String response){
		List<PricePlan> pricePlanList=new ArrayList<PricePlan>();
        StringReader read = new StringReader(response);
        InputSource source = new InputSource(read);
        SAXBuilder builder = new SAXBuilder();
        try {      
        	 Document doc = builder.build(source);  
        	 Element root = doc.getRootElement();
             XPath rateXPath = XPath.newInstance("//ns:Rate");
        	 rateXPath.addNamespace("ns", "http://www.opentravel.org/OTA/2003/05");
        	 List<Element> ratelist =(List<Element>)rateXPath.selectNodes(root);
        	 
        	 for(int i=0;i<ratelist.size();i++){
        		 PricePlan pricePlan=new PricePlan();
        		 Element rate=ratelist.get(i);
        		 String tstamp=rate.getParentElement().getParentElement().getParentElement().getParentElement().getAttributeValue("TimeStamp");
        		 tstamp=tstamp.substring(0,tstamp.lastIndexOf(".")).replace("T", " ");
        		 System.out.println(tstamp);
        		 pricePlan.setUpdateTime(tstamp);
        		 pricePlan.setHotelCode(rate.getParentElement().getParentElement().getParentElement().getAttributeValue("HotelCode"));
        		 pricePlan.setRatePlanCode(rate.getParentElement().getParentElement().getAttributeValue("RatePlanCode"));
    			 pricePlan.setRatePlanCategory(rate.getParentElement().getParentElement().getAttributeValue("RatePlanCategory"));
    			 pricePlan.setMarketCode(rate.getParentElement().getParentElement().getAttributeValue("MarketCode"));
    			 pricePlan.setStart(rate.getAttributeValue("Start"));
    			 pricePlan.setEnd(rate.getAttributeValue("End"));
    			 pricePlan.setStatus(rate.getAttributeValue("Status"));
    			 
    			 List<Element> rateChildren =rate.getChildren();
    			 for(int j=0;j<rateChildren.size();j++){
    				 Element rateChild=rateChildren.get(j);
    				 if("BaseByGuestAmts".equals(rateChild.getName())){
    					 
    					 pricePlan.setAmountBeforeTax(((Element)(rateChild.getChildren().get(0))).getAttributeValue("AmountBeforeTax"));
    					 pricePlan.setCurrencyCode(((Element)(rateChild.getChildren().get(0))).getAttributeValue("CurrencyCode"));
    					 pricePlan.setNumberOfGuests(((Element)(rateChild.getChildren().get(0))).getAttributeValue("NumberOfGuests"));
    					
    				 }else if("GuaranteePolicies".equals(rateChild.getName())){
    					 pricePlan.setGuaranteeCode(((Element)(rateChild.getChildren().get(0))).getAttributeValue("GuaranteeCode"));
    				 }else if("CancelPolicies".equals(rateChild.getName())){
    					 Element cancelPolicies=(Element)(rateChild.getChildren().get(0));
    					 pricePlan.setCancelPenaltyStart(cancelPolicies.getAttributeValue("Start"));
    					 pricePlan.setCancelPenaltyEnd(cancelPolicies.getAttributeValue("End"));
    					 pricePlan.setCancelPenalty(((Element)(cancelPolicies.getChildren().get(0))).getAttributeValue("Amount"));//
    					 pricePlan.setListPrice(((Element)(cancelPolicies.getChildren().get(0))).getAttributeValue("ListPrice"));
    					 pricePlan.setCurrencyCode(((Element)(cancelPolicies.getChildren().get(0))).getAttributeValue("CurrencyCode"));//
    				 }else if("TPA_Extensions".equals(rateChild.getName())){
    					 Element rebatePromotion =(Element)(rateChild.getChildren().get(0));
    					 pricePlan.setRebatePromotionCode(rebatePromotion.getAttributeValue("rebatePromotionCode"));
    					 pricePlan.setRebatePromotionCurrencyAmount(rebatePromotion.getAttributeValue("Amount"));
    					 pricePlan.setRebatePromotionCurrencyCode(rebatePromotion.getAttributeValue("CurrencyCode"));
    					 pricePlan.setRebatePromotionStart(rebatePromotion.getAttributeValue("StartPeriod"));
    					 pricePlan.setRebatePromotionEnd(rebatePromotion.getAttributeValue("EndPeriod"));
    					 pricePlan.setRebatePromotionName(rebatePromotion.getAttributeValue("ProgramName"));
    					 Element desc =(Element)(rebatePromotion.getChildren().get(0));
    					 Element text =(Element)(desc.getChildren().get(0));
    					 pricePlan.setRebatePromotionDesc(text.getText());
    				 }
    				 
    			 }		 
        		pricePlanList.add(pricePlan);
        	 }
        	 
        	
        }catch (JDOMException e) {    
    		e.printStackTrace(); 
    		} catch (IOException e) {  
    			e.printStackTrace(); 
    			}
       return pricePlanList;
	}
	
	private static void jdbcPlanRooms(List<PricePlan> pp,String cityCode) throws SQLException{
		Connection con = null;
		con = DBPool.getConnection();
		con.setAutoCommit(false);
		java.sql.PreparedStatement st1 = null;
		if (con != null)
		{System.out.println("connection get....................ok");}
		st1 = con.prepareStatement("update priceplan"+cityCode+" set hotelCode=?,ratePlanCategory=?,marketCode=?,minAdvancedBookingOffset=?," +
				"status=?,amountBeforeTax=?,currencyCode=?,listPrice=?,numberOfGuests=?,cancelPenalty=?,cancelPenaltyStart=?,cancelPenaltyEnd=?," +
				"mealsIncluded=?,rebatePromotionStart=?,rebatePromotionEnd=?,rebatePromotionName=?,rebatePromotionCode=?," +
				"rebatePromotionCurrencyCode=?,rebatePromotionCurrencyAmount=?,rebatePromotionDesc=?,guaranteeCode=?,updatePlanTime=?" +
				" where ratePlanCode=? and starttime>=? and endtime<=?");
		
		for (int row = 0; row < pp.size(); row++) {
		st1.setString(23, pp.get(row).getRatePlanCode());st1.setString(24, pp.get(row).getStart());
		st1.setString(25, pp.get(row).getEnd());
		st1.setString(1, pp.get(row).getHotelCode());
		st1.setString(2, pp.get(row).getRatePlanCategory());st1.setString(3, pp.get(row).getMarketCode());
		st1.setString(4, pp.get(row).getMinAdvancedBookingOffset());st1.setString(5, pp.get(row).getStatus());
		st1.setString(6, pp.get(row).getAmountBeforeTax());st1.setString(7, pp.get(row).getCurrencyCode());
		st1.setString(8, pp.get(row).getListPrice());st1.setString(9, pp.get(row).getNumberOfGuests());
		st1.setString(10, pp.get(row).getCancelPenalty());st1.setString(11, pp.get(row).getCancelPenaltyStart());
		st1.setString(12, pp.get(row).getCancelPenaltyEnd());st1.setString(13, pp.get(row).getMealsIncluded());
		st1.setString(14, pp.get(row).getRebatePromotionStart());st1.setString(15, pp.get(row).getRebatePromotionEnd());
		st1.setString(16, pp.get(row).getRebatePromotionName());st1.setString(17, pp.get(row).getRebatePromotionCode());
		st1.setString(18, pp.get(row).getRebatePromotionCurrencyCode());st1.setString(19, pp.get(row).getRebatePromotionCurrencyAmount());
		st1.setString(20, pp.get(row).getRebatePromotionDesc());st1.setString(21, pp.get(row).getGuaranteeCode());
		//System.out.println(pp.get(row).getUpdateTime());
		st1.setTimestamp(22, Timestamp.valueOf(pp.get(row).getUpdateTime()));
		st1.addBatch();
		}
		st1.executeBatch();
		st1.clearBatch();
		
		con.commit();
		st1.close();
		con.close();
	}
	private static void insertLastUpdateTime(String cityCode) throws SQLException{
		Connection con = null;
		con = DBPool.getConnection();
		con.setAutoCommit(false);
		java.sql.Statement st1 = con.createStatement();
		//2013-05-20 21:10:12
		if (con != null)
		{System.out.println("connection get....................ok");}
		//删除本城市记录然后插入新
		 st1.addBatch("delete from updaterecord where cityCode ='"+cityCode+"')");
		
		 st1.addBatch("insert into updaterecord(times,cityCode)"
				+ " values('"+Timestamp.valueOf(new Date().toLocaleString())+"',"+cityCode+")");
		// con.commit();
		 st1.executeBatch(); 
         con.commit(); 
         st1.close();
		 con.close();
	}
	private static String createHotelRatePlanRequestXml(List<PriceCache> pcl){
		StringBuilder sb = new StringBuilder();
		try {
			sb.append("<Request><Header AllianceID=\"");
			sb.append(ConfigData.AllianceId);
			sb.append("\" SID=\"");
			sb.append(ConfigData.SId);
			sb.append("\" TimeStamp=\"");
			long timestamp = SignatureUtils.GetTimeStamp();
			sb.append(timestamp);
			sb.append("\" Signature=\"");

			String signature = SignatureUtils.CalculationSignature(timestamp
					+ "", ConfigData.AllianceId, ConfigData.SecretKey,
					ConfigData.SId, ConfigData.OTA_HotelRatePlan);
			sb.append(signature);
			sb.append("\" RequestType=\"");
			sb.append(ConfigData.OTA_HotelRatePlan);
			sb.append("\" /><HotelRequest><RequestBody xmlns:ns=\"http://www.opentravel.org/OTA/2003/05\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ns:OTA_HotelRatePlanRQ Version=\"1.0\" TimeStamp=\"");
			sb.append(DateUtil.getDateTimeForInterface("yyyy-MM-dd",new Date()));
			sb.append("\" ><ns:RatePlans>");
            for(int i=0;i<pcl.size();i++){
            	sb.append("<ns:RatePlan><ns:DateRange Start=\"");
            	sb.append(pcl.get(i).getStart());
            	sb.append("\" End=\"");
            	sb.append(pcl.get(i).getEnd());
            	sb.append("\" /><ns:RatePlanCandidates><ns:RatePlanCandidate RatePlanCode=\"");
            	sb.append(pcl.get(i).getRatePlanCode());
            	sb.append("\" AvailRatesOnlyInd=\"false\" ><ns:HotelRefs><ns:HotelRef HotelCode=\"");
            	sb.append(pcl.get(i).getHotelCode());
            	sb.append("\" /></ns:HotelRefs></ns:RatePlanCandidate></ns:RatePlanCandidates></ns:RatePlan>");
			}
            sb.append("</ns:RatePlans></ns:OTA_HotelRatePlanRQ></RequestBody></HotelRequest></Request>");
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
        System.out.println(sb.toString());
		return sb.toString();
	}
	
	private static void jdbcPlanRoomsCacheUpdate(List<PriceCache> pcl) throws SQLException{
		Connection con = null;
		con = DBPool.getConnection();
		con.setAutoCommit(false);
		java.sql.PreparedStatement st1 = null;
		if (con != null)
		{System.out.println("connection get....................ok");}
		//489219  12543  10拼装一次报文  roomlist 
		
		//重新查找价格计划并更新
		
	
	}
	
	public static void sychronizeCache() throws ParseException, SQLException{
		//通过历史记录，查询到本次查询缓存需要的开始时间点（就是上次更新完毕后的该城市最终时间）以及城市
		List<PriceUpdateHistory> history=new ArrayList<PriceUpdateHistory>();
		
		 
		List<PriceCache>  pcl=new ArrayList<PriceCache>();
		for(int j=0;j<history.size();j++){
			List<PricePlan> priceplanl=new ArrayList<PricePlan>();
			//然后去查找是否有缓存变化
			pcl=HotelPriceCacheInfoAdapter.findHotelCacheRatePlan(DateUtil.giveMeInterFaceDateString(
					history.get(j).getTimes()),history.get(j).getCityCode());
			
			int page= (pcl.size()%ConfigData.pageSize==0)?pcl.size()/ConfigData.pageSize:(pcl.size()/ConfigData.pageSize+1);
			for(int i=0;i<page;i++){
				if(i==page){
					//分页查找并将所有的同一个城市的priceplan放在priceplanl
					priceplanl.addAll(i,
					HotelPriceCacheInfoAdapter.findHotelRatePlan(
					HttpAccessAdapter.getResponseFromCtrip(ConfigData.OTA_HotelRatePlan,
							HotelPriceCacheInfoAdapter.createHotelRatePlanRequestXml(pcl.subList(ConfigData.pageSize*i, pcl.size())))));
									}else{
					priceplanl.addAll(i,
					HotelPriceCacheInfoAdapter.findHotelRatePlan(
					HttpAccessAdapter.getResponseFromCtrip(ConfigData.OTA_HotelRatePlan,
							HotelPriceCacheInfoAdapter.createHotelRatePlanRequestXml(pcl.subList(ConfigData.pageSize*i, ConfigData.pageSize*(i+1))))));
				}
				//一次性更新单城市的所有缓存数据变化
				HotelPriceCacheInfoAdapter.jdbcPlanRooms(priceplanl,history.get(j).getCityCode());
			}
			insertLastUpdateTime(history.get(j).getCityCode());
		}
	}
	public static void main(String[] args) throws SQLException,
			InterruptedException, JDOMException, IOException, ParseException {
		
		//通过历史记录，查询到本次查询缓存需要的开始时间点（就是上次更新完毕后的该城市最终时间）以及城市
		//然后去查找是否有缓存变化
		//把变化的价格计划取出来再次去查找，更新价格计划表
		sychronizeCache();
	
	}

}
